<?php

namespace app\web\service;

use app\common\logic\OrderLogic;
use app\common\logic\PayLogic;
use app\common\model\commonModel;
use app\common\model\trCache;
use app\common\model\trCarType;
use app\common\model\trOrder;
use app\common\model\trResource;
use app\common\model\trSystemSet;
use app\common\model\trUser;
use app\common\model\trVehicleLine;
use app\common\util\ErrorCode;
use app\common\util\Tools;
use app\common\util\WxPay;

/**
 * Class Auth
 * @package app\web\service
 * 包车路线服务类
 */
class VehicleService
{
    private $params;
    private $returnData;
    private $mallId = 0;

    public function __construct($data, $params)
    {
        $this->returnData = $data;
        $this->params = $params;
        $this->mallId = request()->mallData["id"];
    }

    // 包车路线页面数据
    public function getIndexData(){
        //获取热门线路
        $hotData = $this->getHotLineByPaint(["page" => 1, "pageSize" => 6]);
        $model = new trVehicleLine();

        // 获取出发地和目的地筛选的数据
        $goData = $destinationDate = [];
        if(($redisObject = redis_object()) !== false) {// 是redis缓存
            $fromData = $redisObject->zRange("{$this->mallId}_".$model->fromCacheText,0,-1, true); // 拿出发地code(score)和线路ID(member)
            if(empty($fromData)){
                $model->toSaveFromCache(); //检查缓存
                $fromData = $redisObject->zRange("{$this->mallId}_".$model->fromCacheText,0,-1, true); // 拿出发地code(score)和线路ID(member)
            }
            if(!empty($fromData)){ // 有数据
                foreach ($fromData as $id => $provinceCodeFrom){ // 出发地
                    if(empty($lineData[$id])){
                        $lineData[$id] = $model->getPCACacheData($id);
                    }
                    $this->getGoData($goData, $id, $provinceCodeFrom, $lineData[$id]);
                    if(empty($destinationDate["temp"][$provinceCodeFrom])) { //  目的地，减少查询次数
                        $destinationDate["temp"][$provinceCodeFrom] = $redisObject->zRange("{$this->mallId}_".$model->toCacheText . $provinceCodeFrom, 0, -1, true); // 拿目的地code(score)和线路ID(member)
                        foreach ($destinationDate["temp"][$provinceCodeFrom] as $dId => $provinceCodeTo) { // 目的地
                            if(empty($lineData[$dId])){ // 因为是在foreach里，$lineData[$dId]可能是空的，外层的$id和$dId不一致
                                $lineData[$dId] = $model->getPCACacheData($dId);
                            }
                            $this->getDestinationData($destinationDate, $dId, $provinceCodeFrom, $provinceCodeTo, $lineData[$dId]);
                        }
                    }
                }
                unset($destinationDate["temp"]);
            }
        }else{ // 直接查数据库
            $database = $model->getFields("id,province_code_from,city_code_from,area_code_from,province_code_to,city_code_to,area_code_to", ["status" => 1, "mall_id" => $this->mallId], false, false);
            foreach ($database as $item) {
                $item = Tools::transferFields($item->getData());
                $lineData[$item["id"]] = $item;
                $this->getGoData($goData, $item["id"], $item["provinceCodeFrom"], $lineData[$item["id"]]);
                $this->getDestinationData($destinationDate, $item["id"], $item["provinceCodeFrom"], $item["provinceCodeTo"], $lineData[$item["id"]]);
            }
        }
        foreach ($goData as &$v){
            foreach ($v["children"] as &$i){
                if(isset($i["children"])){
                    $i["children"] = array_values($i["children"]);
                }
            }
            $v["children"] = array_values($v["children"]);
        }
        foreach ($destinationDate as &$a){
            foreach ($a as &$v) {
                foreach ($v["children"] as &$i) {
                    if (isset($i["children"])) {
                        $i["children"] = array_values($i["children"]);
                    }
                }
                $v["children"] = array_values($v["children"]);
            }
            $a = array_values($a);
        }
        $this->returnData["data"] = ["goData" => array_values($goData), "destinationDate" => $destinationDate, "hotLineData" => $hotData["data"]["list"]];
        return $this->returnData;
    }

    // 根据出发地线路ID获取目的地地区数据
    public function getDestinationByLineId(){
        if (empty($this->params['lineId'])) {
            return ErrorCode::code("params_not_exist", "线路ID");
        }
        if(empty($this->params["lineId"])){ // 没有线路
            $this->returnData['data'] = [];
            return $this->returnData;
        }
        $this->params["lineId"] = explode(",", $this->params["lineId"]);
        $model = new trVehicleLine();
        $destinationDate = [];
        foreach ($this->params["lineId"] as $id) {
            $lineData = $model->getPCACacheData($id);
            $this->getDestinationData($destinationDate, $id, 0, $lineData["provinceCodeTo"], $lineData);
        }
        foreach ($destinationDate[0] as &$a){
            foreach ($a["children"] as &$i) {
                if (isset($i["children"])) {
                    $i["children"] = array_values($i["children"]);
                }
            }
            $a["children"] = array_values($a["children"]);
        }
        $this->returnData["data"] = array_values($destinationDate[0]);
        return $this->returnData;
    }

    // 获取出发地的省市区选择数据
    public function getGoData(&$goData, $id, $provinceCodeFrom, $lineData){
        if($provinceCodeFrom == $lineData["provinceCodeFrom"]){
            if(empty($goData[$provinceCodeFrom])) { // 减少查询次数
                $goData[$provinceCodeFrom] = ["code" => $provinceCodeFrom, "name" => Tools::getNameByPCA($provinceCodeFrom)]; //一级
            }
            if(empty($goData[$provinceCodeFrom]["children"][$lineData["cityCodeFrom"]])) {
                $name = explode(" ", Tools::getNameByPCA($provinceCodeFrom, $lineData["cityCodeFrom"]));
                $goData[$provinceCodeFrom]["children"][$lineData["cityCodeFrom"]] = [
                    "code" => $lineData["cityCodeFrom"], "name" => isset($name[1]) ? $name[1] : "", "lineId" => $id
                ]; //二级
            }
            if(!empty($lineData["areaCodeFrom"])) {
                unset($goData[$provinceCodeFrom]["children"][$lineData["cityCodeFrom"]]["lineId"]);
                if(isset($goData[$provinceCodeFrom]["children"][$lineData["cityCodeFrom"]]["children"][$lineData["areaCodeFrom"]])){
                    $id = "{$goData[$provinceCodeFrom]["children"][$lineData["cityCodeFrom"]]["children"][$lineData["areaCodeFrom"]]["lineId"]},{$id}";
                }
                $name = explode(" ", Tools::getNameByPCA($provinceCodeFrom, $lineData["cityCodeFrom"], $lineData["areaCodeFrom"]));
                $goData[$provinceCodeFrom]["children"][$lineData["cityCodeFrom"]]["children"][$lineData["areaCodeFrom"]] = [
                    "code" => $lineData["areaCodeFrom"], "name" => isset($name[2]) ? $name[2] : "", "lineId" => $id
                ]; //三级
            }
        }
    }

    // 获取目的地的省市区选择数据
    public function getDestinationData(&$destinationDate, $dId, $provinceCodeFrom, $provinceCodeTo, $lineData){
        if(empty($destinationDate[$provinceCodeFrom][$provinceCodeTo])) { // 减少查询次数
            $destinationDate[$provinceCodeFrom][$provinceCodeTo] = ["code" => $provinceCodeTo, "name" => Tools::getNameByPCA($provinceCodeTo)]; //一级
        }
        if(empty($destinationDate[$provinceCodeFrom][$provinceCodeTo]["children"][$lineData["cityCodeTo"]])) {
            $name = explode(" ", Tools::getNameByPCA($provinceCodeTo, $lineData["cityCodeTo"]));
            $destinationDate[$provinceCodeFrom][$provinceCodeTo]["children"][$lineData["cityCodeTo"]] = [
                "code" => $lineData["cityCodeTo"], "name" => isset($name[1]) ? $name[1] : "", "lineId" => $dId
            ]; //二级
        }
        if(!empty($lineData["areaCodeTo"])) {
            unset($destinationDate[$provinceCodeFrom][$provinceCodeTo]["children"][$lineData["cityCodeTo"]]["lineId"]);
            if(isset($destinationDate[$provinceCodeFrom][$provinceCodeTo]["children"][$lineData["cityCodeTo"]]["children"][$lineData["areaCodeTo"]])){
                $dId = "{$destinationDate[$provinceCodeFrom][$provinceCodeTo]["children"][$lineData["cityCodeTo"]]["children"][$lineData["areaCodeTo"]]["lineId"]},{$dId}";
            }
            $name = explode(" ", Tools::getNameByPCA($provinceCodeTo, $lineData["cityCodeTo"], $lineData["areaCodeTo"]));
            $destinationDate[$provinceCodeFrom][$provinceCodeTo]["children"][$lineData["cityCodeTo"]]["children"][$lineData["areaCodeTo"]] = [
                "code" => $lineData["areaCodeTo"], "name" => isset($name[2]) ? $name[2] : "", "lineId" => $dId
            ]; //三级
        }
    }

    // 搜索页的数据
    public function getSearchData(){
        if (!isset($this->params['lineId'])) {
            return ErrorCode::code("params_not_exist", "线路ID");
        }
        if (empty($this->params['chooseTime'])) {
            return ErrorCode::code("params_not_exist", "选择日期");
        }
        if(empty($this->params["lineId"])){ // 没有线路
            $this->returnData['data'] = [];
            return $this->returnData;
        }
        $date = date("Y-m-d");
        if($this->params['chooseTime'] < $date){
            $this->returnData['data'] = []; // 选择日期小于当前时间，就没有线路
            return $this->returnData;
        }
        if(strpos($this->params["lineId"], ",") !== false){
            $filter[] = ["id", "in", explode(",", $this->params["lineId"])];
        }else{
            $filter = ["id" => $this->params["lineId"]];
        }
        $model = new trVehicleLine();
        if(($redisObject = redis_object()) !== false) {// 是redis缓存
            $data = $model->getFields("id,address_from,address_to,price", $filter, false, false);
        }else{
            $field = "id,province_code_from,city_code_from,area_code_from,address_from,province_code_to,city_code_to,area_code_to,address_to,price";
            $data = $model->getFields($field, $filter, false, false);
        }
        if(!$data){
            $this->returnData['data'] = [];
        }else {
            $returnData = [];
            foreach ($data as $k => $item) {
                $item = Tools::transferFields($item->getData());
                $returnData[$k]["id"] = $item["id"];
                $returnData[$k]["price"] = $item["price"];
                if($redisObject !== false) {// 是redis缓存
                    $tempData = $model->getPCACacheData($item["id"]);
                    $tempData["addressFrom"] = $item["addressFrom"];
                    $tempData["addressTo"] = $item["addressTo"];
                    list($returnData[$k]["addressFrom"], $returnData[$k]["addressTo"]) = $this->getShowAddress($tempData);
                }else{
                    list($returnData[$k]["addressFrom"], $returnData[$k]["addressTo"]) = $this->getShowAddress($item);
                }
            }
            $data = $returnData;
            $this->returnData['data'] = $data;
        }
        return $this->returnData;
    }

    // 订单页数据
    public function getOrderData($userId){
        if (empty($this->params['lineId'])) {
            return ErrorCode::code("params_not_exist", "lineId");
        }
        if (empty($this->params['chooseTime'])) {
            return ErrorCode::code("params_not_exist", "选择日期");
        }
        $date = date("Y-m-d");
        if($this->params['chooseTime'] < $date){
            return ErrorCode::code("params_error", "选择日期");
        }
        $model = new trVehicleLine();
        if(($redisObject = redis_object()) !== false) {// 是redis缓存
            $data = $model->getFields("id,address_from,address_to,price", ["id" => $this->params["lineId"]]);
        }else{
            $field = "id,province_code_from,city_code_from,area_code_from,address_from,province_code_to,city_code_to,area_code_to,address_to,car_type,price";
            $data = $model->getFields($field, ["id" => $this->params["lineId"]]);
        }
        if(!$data){
            return ErrorCode::code("not_exist");
        }else {
            if($redisObject !== false) {// 是redis缓存
                $data = array_merge($data, $model->getPCACacheData($data["id"]));
            }
            $carTypeModel = new trCarType();
            $carTypeData = $carTypeModel->getFields("name,seat,icon,remark", ["id" => $data["carType"]]);
            $data["rideNumber"] = $carTypeData["seat"];
            $returnData = [
                "id" => $data["id"],
                "price" => $data["price"],
                "addressFrom" => $data["addressFrom"],
                "addressTo" => $data["addressTo"],
            ];
            $name = explode(" ", Tools::getNameByPCA($data["provinceCodeFrom"], $data["cityCodeFrom"], $data["areaCodeFrom"]));
            $returnData["areaForm"] = isset($name[2]) ? $name[2] : $name[1];
            $name = explode(" ", Tools::getNameByPCA($data["provinceCodeTo"], $data["cityCodeTo"], $data["areaCodeTo"]));
            $returnData["areaTo"] = isset($name[2]) ? $name[2] : $name[1];
            $cacheKey = Tools::createGUID();
            trCache::saveCache(["key" => $cacheKey . $userId, "value" => $data, "time" => 600]);
            $this->returnData['data'] = ["orderKey" => $cacheKey, "lineData" => $returnData, "carData" => $carTypeData, "remark" => $this->getLineRemark()];
        }
        return $this->returnData;
    }

    // 提交订单
    public function toSubmitOrder($userId, $openid){
        $field = [
            "orderKey" => "orderKey", "chooseTime" => "选择日期", "shiftTime" => "选择时间", "contactId" => "联系人", "rideNumber" => "乘车人数"
        ];
        foreach ($field as $k => $v) {
            if(!isset($this->params[$k])){
                $this->returnData = ErrorCode::code('params_not_exist', $v);
                return $this->returnData;
            }
        }
        $cacheData = trCache::getValue("value", ["key" => $this->params["orderKey"] . $userId]);
        if(empty($cacheData)){
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "订单已创建";
            return $this->returnData;
        }
        $contactData = commonModel::getFields(contactTable, "prefix,mobile,name", ["id" => $this->params["contactId"], "user_id" => $userId], true, false);
        if(empty($contactData)){
            return ErrorCode::code("params_error", "contactId（联系人ID）");
        }
        if($cacheData["rideNumber"] < $this->params["rideNumber"]){
            return ErrorCode::code("customized", "超过最大乘车人数");
        }
        // 计算总价、计算佣金
        $totalMoney = $cacheData["price"];
        $commission = 0;
        if(empty($totalMoney)){
            return ErrorCode::code("customized", "线路价格有误");
        }
        // 使用优惠券
        $couponAmount = 0; // 优惠金额
        $userCouponId = 0;     //优惠券id
        if(!empty($this->params['userCouponId']) && !empty($couponInfo = commonModel::getFields(userCouponTable,'amount',['id' => $this->params['userCouponId']]))){
            $userCouponId = $this->params['userCouponId'];
            $couponAmount = $couponInfo['amount'];
        }elseif(!empty($this->params["coupon"]) && !empty($couponInfo = commonModel::getFields(userCouponTable,'id,amount',["coupon_id" => $this->params["coupon"], "user_id" => $userId]))){
            $userCouponId = $couponInfo["id"];
            $couponAmount = $couponInfo['amount'];
        }
        $orderModel = new trOrder();
        $orderSn = $orderModel->getSn();
        $paymentNo = $orderModel->getPayNo();
        $orderData = [
            "order_sn" => $orderSn,
            "mall_id" => $this->mallId,
            "line_id" => $cacheData["id"],
            "user_id" => $userId,
            "address_from" => Tools::getNameByPCA($cacheData["provinceCodeFrom"], $cacheData["cityCodeFrom"], $cacheData["areaCodeFrom"]) . (!empty($cacheData["addressFrom"]) ? " {$cacheData["addressFrom"]}" : ""),
            "address_to" => Tools::getNameByPCA($cacheData["provinceCodeTo"], $cacheData["cityCodeTo"], $cacheData["areaCodeTo"]) . (!empty($cacheData["addressFrom"]) ? " {$cacheData["addressTo"]}" : ""),
            "contact_name" => $contactData["name"],
            "mobile" => $contactData["prefix"].$contactData["mobile"],
            "ride_number" => $this->params["rideNumber"],   // 总票数
            "total_money" => $totalMoney,  // 订单总价格
            "pay_money" => $totalMoney > $couponAmount ? $totalMoney - $couponAmount : 0,  // 去支付的价格
            "discount_money" => $couponAmount, // 没接优惠券，所有默认0
            "commission" => $commission,
            "coupon_id" => $userCouponId,  //新 用户优惠券表 id
            "reserve_time" => $this->params["chooseTime"] . " " . $this->params["shiftTime"], // 预约时间，出发时间
            "type" => 4,   //类型；1机场接送，2巴士线路，3专车接送，4包车路线
            "payment_no" => $paymentNo,
            "memo" => isset($this->params["memo"]) ? $this->params["memo"] : ""
        ];
        if($orderId = $orderModel->add($orderData, true)){
            if(!empty($this->params["formId"]) && strpos($this->params["formId"], "the formId") === false){ // 存 form_id
                commonModel::toAdd(formIdTable, ["user_id" => $userId, "form_id" => $this->params["formId"], "type" => "prepay_id", "create_time" => time(), "mall_id" => $this->mallId]);
            }
            trCache::del($this->params["orderKey"] . $userId);
            if($orderData["pay_money"]) {
                //订单后续操作
                $data = [
                    "total_fee" => $orderData["pay_money"] * 100, "openid" => $openid, "out_trade_no" => $paymentNo, "body" => "包车路线支付"
                ];
                // 加的测试
                if (in_array(request()->host(), ["cardemo.wegouer.com/test/cars-pai", "service-emhatyrq-1251017581.gz.apigw.tencentcs.com/test/cars-pai"])) {
//                $data["total_fee"] = 1; // 测试 1毛
                }
                $wxPay = new WxPay();
                $res = $wxPay->toPay($data); // 获取支付信息
                if (isset($res["code"])) {
                    $this->returnData = $res;
                } else {
                    // 订单有效时间为30分钟，时间一到就要自动取消
                    OrderLogic::cancelOrderJobs($orderSn, ["orderSn" => $orderSn, "userId" => $userId]);
                    $res["orderSn"] = $orderSn;
                    $this->returnData["data"] = $res;
                }
            }else{
                $payLogic = new PayLogic();
                $userModel = new trUser();
                $payLogic->updateOrder($paymentNo, ["tradeNo" => "", "totalFee" => 0, "payAccount" => $userModel->getValue("nickname", ["id" => $userId])]);
                $this->returnData["data"] = ["orderSn" => $orderSn];
            }
        }else{
            $this->returnData = ErrorCode::code("fail");
            $this->returnData["msg"] = "生成订单失败";
        }
        return $this->returnData;
    }

    // 小程序的线路地址展示，显示2级，后面优先
    public static function getShowAddress($data){
        $name = explode(" ", Tools::getNameByPCA($data["provinceCodeFrom"], $data["cityCodeFrom"], $data["areaCodeFrom"]));
        $addressFrom = (isset($name[2]) ? $name[2] : $name[1]) . "-{$data["addressFrom"]}";
        $name = explode(" ", Tools::getNameByPCA($data["provinceCodeTo"], $data["cityCodeTo"], $data["areaCodeTo"]));
        $addressTo = (isset($name[2]) ? $name[2] : $name[1]) . "-{$data["addressTo"]}";
        return [$addressFrom, $addressTo];
    }

    public function getLineRemark(){
        $lineRemarkData = trSystemSet::getValue("vehicleRemarks");
        if(empty($lineRemarkData)){
            $lineRemarkData = [
                "vehicleRemarks" => "",   //包车路线备注
                "vehicleAlias" => "包车线路",   //包车线路备注
                "hotLineBanner" => "/attachment/default/hotline-1.jpg",
                "hotLineRemark" => "热门线路"
            ];
            $lineRemarkData["hotLineBannerUrl"] = tome_dia($lineRemarkData["hotLineBanner"]);
        }else{
            $lineRemarkData["hotLineBannerUrl"] = tome_dia(trResource::getValue("url", ["id" => $lineRemarkData["hotLineBanner"]]));
        }
        return $lineRemarkData;
    }

    // 获取可用的热门线路列表，分页
    public function getHotLineByPaint(){
        $model = new trVehicleLine();
        $page = isset($this->params['page']) ? $this->params['page'] : 1;
        $pageSize = isset($this->params['pageSize']) ? $this->params['pageSize'] : 10;
        if(($redisObject = redis_object()) !== false) {// 是redis缓存
            $data = $model->getList("id,address_from,address_to,price", ["status" => 1, "hot" => 2, "mall_id" => $this->mallId], $page, $pageSize, "create_time desc");
        }else{
            $field = "id,province_code_from,city_code_from,area_code_from,address_from,province_code_to,city_code_to,area_code_to,address_to,price";
            $data = $model->getList($field, ["status" => 1, "hot" => 2, "mall_id" => $this->mallId], $page, $pageSize, "create_time desc");
        }
        if(!$data["data"]){
            $this->returnData['data'] = array_merge($this->getLineRemark(), ['list' => [], 'totalPage' => $page, 'currentPage' => $page, 'count' => 0]);
        }else {
            $returnData = [];
            if($redisObject !== false) {// 是redis缓存
                foreach ($data["data"] as $k => $item) {
                    $returnData[$k]["id"] = $item["id"];
                    $returnData[$k]["showPrice"] = $item["price"];
                    $tempData = $model->getPCACacheData($item["id"]);
                    $tempData["addressFrom"] = $item["addressFrom"];
                    $tempData["addressTo"] = $item["addressTo"];
                    list($returnData[$k]["addressFrom"], $returnData[$k]["addressTo"]) = $this->getShowAddress($tempData);
                }
            }else{
                foreach ($data["data"] as $k => $item) {
                    $returnData[$k]["id"] = $item["id"];
                    $returnData[$k]["showPrice"] = $item["price"];
                    list($returnData[$k]["addressFrom"], $returnData[$k]["addressTo"]) = $this->getShowAddress($item);
                }
            }
            $this->returnData['data'] = array_merge($this->getLineRemark(), ['list' => $returnData, 'totalPage' => $data['last_page'], 'currentPage' => $data['current_page'], 'count' => $data['total']]);
        }
        return $this->returnData;
    }
}